In the standard library, several functions, instead of taking an object as an argument, take a list of arguments that will be used to construct an
object in a specific place:
-
std::vector::emplace_back
will create the object directly inside the vector
-
std::make_unique
will create the object and a unique_ptr
that points to it
-
std::make_shared
will create the object in a specially allocated memory area that will also contain bookkeeping information for
the shared pointer, and the associated shared_ptr
-
std::optional
has a constructor that will create an object inside the optional (this constructor is selected by using
std::in_place
as its first argument)
- …
These functions are said to perform delegated object creation.
Constructing an object externally and passing it to one of these functions is possible. They will then create their object by calling the copy
constructor to copy the argument. But it defeats the purpose of those functions that try to create the object at the right place directly.
This rule raises an issue when a function that performs delegated object creation is passed an object of the right type explicitly created for this
purpose only.
Noncompliant code example
struct Point {
Point(int x, int y);
Point(std::string_view serialized);
};
void f() {
auto p1 = std::make_unique<Point>(Point(1, 2)); // Noncompliant
auto p2 = std::optional<Point>(std::in_place, Point(1, 2)); // Noncompliant
std::vector<Point> points;
points.emplace_back(Point {1, 2}); // Noncompliant
Point p {3, 4};
points.emplace_back(p); // Noncompliant, since p is not used anywhere else
}
Compliant solution
struct Point {
Point(int x, int y);
Point(std::string_view serialized);
};
void f() {
auto p1 = std::make_unique<Point>(1, 2); // Compliant
auto p2 = std::optional<Point>(std::in_place, 1, 2); // Compliant
std::vector<Point> points;
points.emplace_back(1, 2); // Compliant
Point p {3, 4};
points.emplace_back(p); // Compliant
someFunction(p);
auto buffer = "1,3";
points.emplace_back(std::string_view{buffer, 3}) // Compliant, the constructed object is of a different type
}